package com.exam.api.modules.file.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.text.StrJoiner;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.exam.api.common.exception.GlobalException;
import com.exam.api.modules.file.dto.FileBase64DTO;
import com.exam.api.modules.file.service.TblFileService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.FileStorageService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;

/**
 * @Author bcheng
 * @Create 2023/12/25 17:54
 * @Description 文件相关逻辑
 */
@Slf4j
@Service
public class TblFileServiceImpl implements TblFileService {

    @Resource
    @Lazy
    private FileStorageService fileStorageService;

    private final static Duration TEMP_FILE_EXPIRE_TIME = Duration.ofDays(30);

    private final static String TEMP_FOLDER = "temp";

    private final static String SYS_FOLDER = "sys";


    @Override
    public FileInfo uploadSysFile(MultipartFile file) {
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        return uploadSysFile(tokenInfo, file);
    }

    @Override
    public FileInfo uploadSysFile(SaTokenInfo tokenInfo, MultipartFile file) {
        String path = StrJoiner.of(StrPool.SLASH)
                .setSuffix(StrPool.SLASH)
                .append(SYS_FOLDER)
                .append(tokenInfo.getLoginId())
                .append(LocalDate.now().format(DatePattern.PURE_DATE_FORMATTER))
                .toString();
        FileInfo fileInfo = fileStorageService.of(file)
                .setObjectId(tokenInfo.getLoginId())
                .setObjectType(tokenInfo.getLoginDeviceType())
                .setPath(path)
                .upload();
        return fileInfo;
    }


    @Override
    public FileInfo uploadTempFile(MultipartFile file) {
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        String path = StrJoiner.of(StrPool.SLASH)
                .setSuffix(StrPool.SLASH)
                .append(TEMP_FOLDER)
                .append(tokenInfo.getLoginId())
                .append(LocalDate.now().format(DatePattern.PURE_DATE_FORMATTER))
                .toString();
        FileInfo fileInfo = fileStorageService.of(file)
                .setObjectId(tokenInfo.getLoginId())
                .setObjectType(tokenInfo.getLoginDeviceType())
                .putAttr("expireTime", LocalDateTime.now().plus(TEMP_FILE_EXPIRE_TIME))
                .setPath(path)
                .upload();
        return fileInfo;
    }

    @Override
    public FileInfo uploadTempFile(InputStream in) {
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        String path = StrJoiner.of(StrPool.SLASH)
                .setSuffix(StrPool.SLASH)
                .append(TEMP_FOLDER)
                .append(tokenInfo.getLoginId())
                .append(LocalDate.now().format(DatePattern.PURE_DATE_FORMATTER))
                .toString();
        FileInfo fileInfo = fileStorageService.of(in)
                .setObjectId(tokenInfo.getLoginId())
                .setObjectType(tokenInfo.getLoginDeviceType())
                .putAttr("expireTime", LocalDateTime.now().plus(TEMP_FILE_EXPIRE_TIME))
                .setPath(path)
                .upload();
        return fileInfo;
    }

    @Override
    public FileInfo uploadFile(MultipartFile file) {
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        String path = StrJoiner.of(StrPool.SLASH)
                .setSuffix(StrPool.SLASH)
                .append(tokenInfo.getLoginId())
                .append(LocalDate.now().format(DatePattern.PURE_DATE_FORMATTER))
                .toString();
        FileInfo fileInfo = fileStorageService.of(file)
                .setObjectId(tokenInfo.getLoginId())
                .setObjectType(tokenInfo.getLoginDeviceType())
                .setPath(path)
                .upload();
        return fileInfo;
    }

    @Override
    public FileInfo uploadFileBase64(FileBase64DTO dto) {
        String base64Data = dto.getBase64();
        if (base64Data == null) throw new GlobalException("内容空");
        String[] parts = base64Data.split(",");
        byte[] encode = Base64.decode(parts[1].getBytes());
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        String path = StrJoiner.of(StrPool.SLASH)
                .setSuffix(StrPool.SLASH)
                .append(tokenInfo.getLoginId())
                .append(LocalDate.now().format(DatePattern.PURE_DATE_FORMATTER))
                .toString();
        String name = System.currentTimeMillis() + UUID.randomUUID().toString() + ".jpg";
//        ByteArrayInputStream stream = new ByteArrayInputStream(imageBytes);
        FileInfo fileInfo = fileStorageService.of(encode)
                .setName(name)
                .setObjectId(tokenInfo.getLoginId())
                .setObjectType(tokenInfo.getLoginDeviceType())
                .setPath(path)
                .upload();
        return fileInfo;
    }


    @Override
    public FileInfo uploadFile(File file) {
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        String path = StrJoiner.of(StrPool.SLASH)
                .setSuffix(StrPool.SLASH)
                .append(tokenInfo.getLoginId())
                .append(LocalDate.now().format(DatePattern.PURE_DATE_FORMATTER))
                .toString();
        FileInfo fileInfo = fileStorageService.of(file)
                .setObjectId(tokenInfo.getLoginId())
                .setObjectType(tokenInfo.getLoginDeviceType())
                .setPath(path)
                .upload();
        return fileInfo;
    }

    @Override
    public FileInfo uploadFile(byte[] bytes) {
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
//        String deviceType = "unknown";
        String deviceType = StrUtil.blankToDefault(tokenInfo.getLoginDeviceType(), "unknown");
//        Object loginId = 1L;
        Object loginId = ObjUtil.defaultIfNull(tokenInfo.getLoginId(), 1L);
        String path = StrJoiner.of(StrPool.SLASH)
                .setSuffix(StrPool.SLASH)
                .append(loginId)
                .append(LocalDate.now().format(DatePattern.PURE_DATE_FORMATTER))
                .toString();
        return fileStorageService.of(bytes)
                .setObjectId(loginId)
                .setObjectType(deviceType)
                .setPath(path)
                .upload();
    }
}
